/*
Copyright 2009 David Revell

This file is part of SwiFTP.

SwiFTP is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

SwiFTP is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with SwiFTP.  If not, see <http://www.gnu.org/licenses/>.
*/

package lfr.ustc.ftp;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

public class CmdRETR extends CmdManager implements Runnable {
	protected String input;

	public CmdRETR(SocketManager sessionThread, String input) {
		super(sessionThread);
		this.input = input;
	}
	public void run() {
		String param = getParameter(input);
		File fileToRetr;
		String errString = null;

		mainblock: {
			fileToRetr = inputPathToChrootedFile(sessionThread.getWorkingDir(),
					param);
			if (violatesChroot(fileToRetr)) {
				errString = "550 Invalid name or chroot violation\r\n";
				break mainblock;
			} else if (fileToRetr.isDirectory()) {
				errString = "550 Can't RETR a directory\r\n";
				break mainblock;
			} else if (!fileToRetr.exists()) {

				errString = "550 File does not exist\r\n";
				break mainblock;
			} else if (!fileToRetr.canRead()) {
				errString = "550 No read permissions\r\n";
				break mainblock;
			} 
			try {
				FileInputStream in = new FileInputStream(fileToRetr);
				byte[] buffer = new byte[12040];
				int bytesRead;
				if (sessionThread.startUsingDataSocket()) {
				} else {
					errString = "425 Error opening socket\r\n";
					break mainblock;
				}
				sessionThread.sendInfo("150 Sending file\r\n");
				if (sessionThread.transmitType.equals("BINARY")) {
					while ((bytesRead = in.read(buffer)) != -1) {
						if (sessionThread.sendData(buffer, 0,bytesRead) == false) {
							errString = "426 Data socket error\r\n";
							break mainblock;
						}
					}
				} else {
					boolean lastBufEndedWithCR = false;
					while ((bytesRead = in.read(buffer)) != -1) {
						int startPos = 0, endPos = 0;
						byte[] crnBuf = { '\r', '\n' };
						for (endPos = 0; endPos < bytesRead; endPos++) {
							if (buffer[endPos] == '\n') {
								sessionThread.sendData(buffer,
										startPos, endPos - startPos);
								if (endPos == 0) {
									if (!lastBufEndedWithCR) {
										sessionThread.sendData(crnBuf,0,
												1);
									}
								} else if (buffer[endPos - 1] != '\r') {
									sessionThread.sendData(crnBuf, 0,1);
								} else {
								}
								startPos = endPos;
							}
						}
						sessionThread.sendData(buffer, startPos,
								endPos - startPos);
						if (buffer[bytesRead - 1] == '\r') {
							lastBufEndedWithCR = true;
						} else {
							lastBufEndedWithCR = false;
						}
					}
				}
			} catch (FileNotFoundException e) {
				errString = "550 File not found\r\n";
				break mainblock;
			} catch (IOException e) {
				errString = "425 Network error\r\n";
				break mainblock;
			}
		}
		sessionThread.closeDataSocket();
		if (errString != null) {
			sessionThread.sendInfo(errString);
		} else {
			sessionThread.sendInfo("226 Transmission finished\r\n");
		}
	}
}
